home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / amphn192.lha / src / TCPQueue.c < prev    next >
C/C++ Source or Header  |  1996-11-16  |  5KB  |  207 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. #include <exec/types.h>
  5.  
  6. #include <exec/lists.h>
  7. #include <exec/memory.h>
  8.  
  9. #include <clib/exec_protos.h>
  10. #include <clib/alib_protos.h>
  11.  
  12. #include <errno.h>
  13. #include <inetd.h>
  14. #include <sys/types.h>
  15.  
  16. #include <proto/socket.h>
  17. #include <sys/errno.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/syslog.h>
  22. #include <pragmas/socket_pragmas.h>
  23.  
  24. #include "AmiPhone.h"
  25. #include "TCPQueue.h"
  26.  
  27. #define MEMORY_RESERVE 30000
  28.  
  29. extern LONG sTCPSocket;
  30. extern ULONG ulBytesSentSince;
  31.  
  32. static struct List * TCPQueue[11] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  33. static int nNumTCPPackets[11], nNumTCPBytes[11];
  34.  
  35. static struct Node * AllocTCPNode(UBYTE * pubData, ULONG ulDataLen);
  36. static void FreeTCPNode(struct Node * node);
  37.  
  38. int TCPQueueLength(int nQNum)
  39. {
  40.     return(nNumTCPPackets[nQNum]);
  41. }
  42.  
  43. int TCPQueueBytes(int nQNum)
  44. {
  45.     return(nNumTCPBytes[nQNum]);
  46. }
  47.  
  48. /* Sends TCP data, or queues it, as necessary */
  49. /* Returns the number of bytes actually sent over the line */
  50. /* (Bytes queued will be accounted for later!) */
  51. int AttemptTCPSend(LONG sSendSocket, int nQNum, UBYTE * data, ULONG ulDataLen)
  52. {
  53.     int nSendLen, nReduceSent = ReduceTCPQueue(nQNum, sSendSocket);
  54.     
  55.     if (TCPQueueLength(nQNum) == 0)
  56.     {
  57.         /* attempt immediate send */
  58.         nSendLen = send(sSendSocket, data, ulDataLen, 0L);
  59.         if (nSendLen < 0)     /* unsuccessful send */
  60.         {    
  61.             QueueTCPData(nQNum, data, ulDataLen);
  62.             return(nReduceSent);
  63.         }
  64.         /* successful send */
  65.         if (nSendLen == ulDataLen) return(nSendLen+nReduceSent);
  66.  
  67.         /* partial send! */
  68.         QueueTCPData(nQNum, data+nSendLen, ulDataLen-nSendLen);
  69.         return(nSendLen+nReduceSent);
  70.     }
  71.     /* Other stuff queued... have to send that before we send this */
  72.     QueueTCPData(nQNum, data, ulDataLen);
  73.     return(nReduceSent);
  74. }
  75.  
  76.  
  77. /* Returns success or failure */
  78. BOOL SetupTCPQueue(int nQNum, BOOL BSetup)
  79. {
  80.     if (BSetup == (TCPQueue[nQNum] != NULL)) return(FALSE);    
  81.  
  82.     if (BSetup)
  83.     {
  84.         UNLESS(TCPQueue[nQNum] = AllocMem(sizeof(struct List),MEMF_CLEAR)) return(FALSE);
  85.         NewList(TCPQueue[nQNum]);
  86.         nNumTCPPackets[nQNum] = 0;
  87.         nNumTCPBytes[nQNum] = 0;
  88.     }
  89.     else
  90.     {
  91.         FlushTCPQueue(nQNum);
  92.         FreeMem(TCPQueue[nQNum], sizeof(struct List));
  93.         TCPQueue[nQNum] = NULL;
  94.     }
  95.     return(TRUE);
  96. }
  97.  
  98.  
  99. void FlushTCPQueue(int nQNum)
  100. {
  101.     struct Node * current;
  102.     
  103.     if (TCPQueue[nQNum])
  104.     {
  105.         while(current = RemHead(TCPQueue[nQNum])) FreeTCPNode(current);
  106.         nNumTCPPackets[nQNum] = 0;
  107.         nNumTCPBytes[nQNum] = 0;
  108.     }
  109. }
  110.  
  111.  
  112. /* Copy given buffer and store it in our queue */
  113. BOOL QueueTCPData(int nQNum, UBYTE * pubData, ULONG ulLen)
  114. {
  115.     struct Node * pNewNode;
  116.     
  117.     UNLESS(pNewNode = AllocTCPNode(pubData, ulLen)) return(FALSE);
  118.     AddTail(TCPQueue[nQNum], pNewNode);
  119.     nNumTCPPackets[nQNum]++;
  120.     nNumTCPBytes[nQNum] += ulLen;
  121.     return(TRUE);
  122. }
  123.  
  124.  
  125.  
  126. /* Send as much data as we can */
  127. /* Returns the number of bytes sent this time through */
  128. int ReduceTCPQueue(int nQNum, LONG sSendSocket)
  129. {
  130.     struct Node * current, * partial;
  131.     UBYTE * data;
  132.     ULONG ulDataLen;
  133.     int nSent, nReturn = 0;
  134.         
  135.     while(current = RemHead(TCPQueue[nQNum]))
  136.     {
  137.         memcpy(&ulDataLen, current->ln_Name, sizeof(ULONG));
  138.  
  139.         nNumTCPPackets[nQNum]--;
  140.         nNumTCPBytes[nQNum] -= ulDataLen;
  141.         
  142.         data  = current->ln_Name + sizeof(ULONG);
  143.         nSent = send(sSendSocket, data, ulDataLen, 0L);
  144.         nReturn += (nSent > 0) ? nSent : 0;
  145.         
  146.         if (nSent >= ((int)ulDataLen))
  147.         {
  148.             /* All data sent--okay to get rid of this packet! */
  149.             FreeTCPNode(current);
  150.         }
  151.         else if (nSent <= 0)
  152.         {
  153.             /* oops, we're all full--put this packet back */
  154.             AddHead(TCPQueue[nQNum], current);
  155.             nNumTCPPackets[nQNum]++;
  156.             nNumTCPBytes[nQNum] += ulDataLen;
  157.             return(nReturn);
  158.         }
  159.         else
  160.         {
  161.             /* only part of our data was sent.  Make a new 
  162.                packet containing the rest and re-queue it. */
  163.             partial = AllocTCPNode(data+nSent, ulDataLen-nSent);
  164.             FreeTCPNode(current);
  165.             if (partial) 
  166.             {
  167.                 AddHead(TCPQueue[nQNum], partial);
  168.                 nNumTCPPackets[nQNum]++;
  169.                 nNumTCPBytes[nQNum] += (ulDataLen-nSent);
  170.             }
  171.             else printf("TCPReduceQueue:  Error:  Couldn't allocate partial node for next send!\n");
  172.             return(nReturn);
  173.         }
  174.     }
  175. }
  176.  
  177.  
  178.  
  179. static struct Node * AllocTCPNode(UBYTE * pubData, ULONG ulDataLen)
  180. {
  181.     UBYTE * pubNewBuffer;
  182.     struct Node * pNewNode;
  183.  
  184.     if (AvailMem(MEMF_ANY) < MEMORY_RESERVE) return(NULL);
  185.     UNLESS(pNewNode = AllocMem(sizeof(struct Node), MEMF_CLEAR)) return(NULL);
  186.     UNLESS(pubNewBuffer = AllocMem(ulDataLen+sizeof(ULONG), MEMF_ANY))
  187.     {
  188.         FreeMem(pNewNode, sizeof(struct Node));
  189.         return(NULL);
  190.     }
  191.     pNewNode->ln_Name = pubNewBuffer;
  192.     memcpy(pubNewBuffer, &ulDataLen, sizeof(ULONG));
  193.     memcpy(pubNewBuffer+sizeof(ULONG), pubData, ulDataLen);
  194.     return(pNewNode);
  195. }
  196.  
  197.  
  198.  
  199. static void FreeTCPNode(struct Node * node)
  200. {
  201.     UBYTE * data = node->ln_Name;
  202.     ULONG ulDataLen;
  203.     
  204.     memcpy(&ulDataLen, data, sizeof(ULONG));    
  205.     FreeMem(data, ulDataLen + sizeof(ULONG));
  206.     FreeMem(node, sizeof(struct Node));
  207. }